import {
  computed, getCurrentInstance, ref, watch
} from 'vue';
import { cloneFnJSON, isDef, isFunction } from './shared';

/**
 * v-model的简写, props + emit -> ref
 * @param props
 * @param key
 * @param emit
 * @param options
 */
export function useVModel(props, key = 'modelValue', emit, options = {}) {
  const {
    clone = false,
    // 当 passive 设置为 true 时，它将使用 watch 与 props 和 ref 同步。
    // 而不是依赖 `v-model` 或 `.sync` 来工作。
    passive = false,
    // 使用其他的事件名抛出
    eventName,
    // watch 的 deep参数 passive为true时生效
    deep = false,
    // 在没有传递值时为return ref定义默认值
    defaultValue
  } = options;
  // 获取当前组件实例
  const vm = getCurrentInstance();
  console.log(vm);
  const _emit = emit || vm.emit || vm.proxy.$emit.bind(vm.proxy);
  let event = eventName;
  event = eventName || event || `update:${key.toString()}`;

  // eslint-disable-next-line no-nested-ternary
  const cloneFn = (val) => (!clone ? val : isFunction(clone) ? clone(val) : cloneFnJSON(val));

  // 深拷贝props[key] 或者 取默认值
  const getValue = () => (isDef(props[key])
    ? cloneFn(props[key])
    : defaultValue);
  // passive 为true 则使用watch方法 监听变化
  if (passive) {
    const initialValue = getValue();
    const proxy = ref(initialValue);
    // 变更props[key]同时 变更 proxy并深拷贝
    watch(() => props[key], (v) => proxy.value = cloneFn(v));
    // 变更 proxy 调用emit 并传入已深拷贝的值
    watch(proxy, (v) => {
      if (v !== props[key] || deep) _emit(event, v);
    }, { deep });
    return proxy;
  }
  return computed({
    get() {
      return getValue();
    },
    set(value) {
      _emit(event, value);
    }
  });
}
